package com.java.simple.study.juc.p7;

import com.java.simple.study.tool.Sleeper;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author zhoujunlin
 * @date 2022年08月21日 11:37
 * @desc
 */
@Slf4j(topic = "c.TestAQS")
public class TestAQS {

    public static void main(String[] args) {
        //testLock();
        MyLock myLock = new MyLock();
        myLock.lock();
        try {
            log.debug("locking step1...");
            // 不可重入
            myLock.lock();
            log.debug("locking step2...");
        } finally {
            log.debug("unlocking...");
            myLock.unlock();
        }
    }


    private static void testLock() {
        MyLock myLock = new MyLock();
        new Thread(() -> {
            myLock.lock();
            try {
                log.debug("locking...");
                Sleeper.sleep(1);
            } finally {
                log.debug("unlocking...");
                myLock.unlock();
            }
        }, "t1").start();

        new Thread(() -> {
            // 阻塞式锁
            myLock.lock();
            try {
                log.debug("locking...");
            } finally {
                log.debug("unlocking...");
                myLock.unlock();
            }
        }, "t2").start();
    }

}

/**
 * 自定义锁-不可冲入锁
 */
class MyLock implements Lock {

    /**
     * 独占锁  同步器类 继承aqs
     */
    class MySync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int acquires) {
            if (acquires == 1) {
                if (compareAndSetState(0, 1)) {
                    // 加上了锁  并设置owner为当前线程
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int acquires) {
            if (acquires == 1) {
                if (getState() == 0) {
                    throw new IllegalMonitorStateException();
                }
                // 不需要cas  因为只有锁的持有者才可以释放
                setExclusiveOwnerThread(null);
                setState(0);
                return true;
            }
            return false;
        }

        @Override
        protected boolean isHeldExclusively() {
            // 是否持有独占锁
            return getState() == 1;
        }

        public Condition newCondition() {
            return new ConditionObject();
        }
    }

    private MySync sync = new MySync();

    @Override
    public void lock() {
        // 加锁  不成功会进入等待队列
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        // 加锁  可打断
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        // 尝试加锁（一次）
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        // 尝试加锁  带超时
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        // 解锁
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }
}
